package rfBio;
import java.io.*;
import java.util.*;
import rfBio.*;

public class fasta {
	// ***********************
	//private data fields
	// ***********************
	
	private Vector fastaVector = new Vector(100, 100);
	private boolean isProtein = true;
	private boolean isDNA = false;
	private boolean isRNA = false;
//	private Set aminoacids = new HashSet();
//	private Set DNA = new HashSet();
//	private Set RNA = new HashSet();


	//***********************
	// private methods
	//***********************

	/*private void init_aa(){
		aminoacids.add("A");
		aminoacids.add("R");
		aminoacids.add("N");
		aminoacids.add("D");
		aminoacids.add("C");
		aminoacids.add("Q");
		aminoacids.add("E");
		aminoacids.add("G");
		aminoacids.add("H");
		aminoacids.add("I");
		aminoacids.add("L");
		aminoacids.add("K");
		aminoacids.add("M");
		aminoacids.add("F");
		aminoacids.add("P");
		aminoacids.add("S");
		aminoacids.add("T");
		aminoacids.add("W");
		aminoacids.add("Y");
		aminoacids.add("V");
		aminoacids.add("X");
		aminoacids.add(".");
		aminoacids.add("a");
		aminoacids.add("r");
		aminoacids.add("n");
		aminoacids.add("d");
		aminoacids.add("c");
		aminoacids.add("q");
		aminoacids.add("e");
		aminoacids.add("g");
		aminoacids.add("h");
		aminoacids.add("i");
		aminoacids.add("l");
		aminoacids.add("k");
		aminoacids.add("m");
		aminoacids.add("f");
		aminoacids.add("p");
		aminoacids.add("s");
		aminoacids.add("t");
		aminoacids.add("w");
		aminoacids.add("y");
		aminoacids.add("v");
		aminoacids.add("x");
	}
	
	private void init_DNA(){
		DNA.add("A");
		DNA.add("T");
		DNA.add("G");
		DNA.add("C");
		DNA.add("N");
		DNA.add("a");
		DNA.add("t");
		DNA.add("g");
		DNA.add("c");
		DNA.add("n");
	}
	
	private void init_RNA(){
		RNA.add("A");
		RNA.add("U");
		RNA.add("G");
		RNA.add("C");
		RNA.add("N");
		RNA.add("a");
		RNA.add("u");
		RNA.add("g");
		RNA.add("c");
		RNA.add("n");
	}*/
	private void read_fasta(String fasta_filename)
		throws IOException, FileNotFoundException {
		
		
		// ********************
		// local variables
		// ********************
		
		fasta_seq temp_seq = new fasta_seq();
		String t_seq="";


		
		// ***************************************************
		// read file section
		// ***************************************************
		
		// open fasta file
		BufferedReader fastaFile = new BufferedReader ( new FileReader (fasta_filename));
		
		String line = fastaFile.readLine();
		// skip to first non_empty line
		while( line.length() < 1){
			line = fastaFile.readLine();
		}

		while (true){
			// it is a tag so store it in temporary fasta_seq

			temp_seq.set_tag(line.substring(1));
			
			// skip to first non_empty line

			while( line.length() < 1){
				line = fastaFile.readLine();
			}
			line = fastaFile.readLine();
			// skip to first non_empty line
			while( line.length() < 1){
				line = fastaFile.readLine();
			}
			if (line == null)
			{
				break;
			}
			while( line.charAt(0) != '>'){
    			t_seq = t_seq + line;
    			line = fastaFile.readLine();
    			// skip to first non_empty line
    			if( line == null){
    				break;
    			}
    			while( line.length() < 1){
    				line = fastaFile.readLine();
    			}
    		}
			temp_seq.set_seq(t_seq);

			fastaVector.add(new fasta_seq(temp_seq));
			t_seq = "";

			if (line==null)
			{
				break;
			}

		} // end while, here we have reached end of file
		
		fastaFile.close();
	}
	
	
	
	private void read_fastaex(String fasta_filename, String exclude_tablename)
		throws IOException, FileNotFoundException {
		// ********************
		// local variables
		// ********************
		
		fasta_seq temp_seq = new fasta_seq();
		String t_seq="";
		Vector exTable = new Vector(100,100);
		boolean add_flag = true; 

		
		// ***************************************************
		// read file section
		// ***************************************************
		
		
		//open list of names to exclude
		BufferedReader excludeTable = new BufferedReader ( new FileReader (exclude_tablename));
		
		// read exclude table
		while(true){
			String exline = excludeTable.readLine();
			if(exline == null){
				break;
			}
			exTable.add(exline);			
		}
		
		// open fasta file
		BufferedReader fastaFile = new BufferedReader ( new FileReader (fasta_filename));
		
		String line = fastaFile.readLine();
		// skip to first non_empty line
		while( line.length() < 1){
			line = fastaFile.readLine();
		}

		while (true){
			// it is a tag so store it in temporary fasta_seq

			temp_seq.set_tag(line.substring(1));
			// skip to first non_empty line

			while( line.length() < 1){
				line = fastaFile.readLine();
			}
			line = fastaFile.readLine();
			// skip to first non_empty line
			while( line.length() < 1){
				line = fastaFile.readLine();
			}
			if (line == null)
			{
				break;
			}
			while( line.charAt(0) != '>'){
    			t_seq = t_seq + line;
    			line = fastaFile.readLine();
    			// skip to first non_empty line
    			if( line == null){
    				break;
    			}
    			while( line.length() < 1){
    				line = fastaFile.readLine();
    			}
    		}
			temp_seq.set_seq(t_seq);
			
			
			for(int i = 0; i < exTable.size(); i++){
				if(temp_seq.get_tag().startsWith((String) exTable.get(i))){
					add_flag = false;
					break;
				}		
			}
			if(add_flag == true){
				fastaVector.add(new fasta_seq(temp_seq));
			}
			
	//		if(add_flag == false){
				// System.out.println("Removed " + temp_seq.get_tag());
		//	}
			add_flag = true;
			t_seq = "";

			if (line==null)
			{
				break;
			}

		} // end while, here we have reached end of file
		
		fastaFile.close();
		
	}
	
	private void read_fastainc(String fasta_filename, String include_tablename)
		throws IOException, FileNotFoundException {
			// ********************
			// local variables
			// ********************
			
			fasta_seq temp_seq = new fasta_seq();
			String t_seq="";
			Vector incTable = new Vector(100,100);
			boolean add_flag = false; 


			
			// ***************************************************
			// read file section
			// ***************************************************
			
			
			//open list of names to exclude
			BufferedReader includeTable = new BufferedReader ( new FileReader (include_tablename));
			
			// read exclude table
			while(true){
				String incline = includeTable.readLine();
				if(incline == null){
					break;
				}
				incTable.add(incline);
				//System.out.println(incline);
			}
			//System.out.println(incTable.size());
			
			// open fasta file
			BufferedReader fastaFile = new BufferedReader ( new FileReader (fasta_filename));
			
			String line = fastaFile.readLine();
			// skip to first non_empty line
			while( line.length() < 1){
				line = fastaFile.readLine();
			}

			while (true){
				// it is a tag so store it in temporary fasta_seq
				
				temp_seq.set_tag(line.substring(1));
				// skip to first non_empty line

				while( line.length() < 1){
					line = fastaFile.readLine();
				}
				line = fastaFile.readLine();
				// skip to first non_empty line
				while( line.length() < 1){
					line = fastaFile.readLine();
				}
				if (line == null)
				{
					break;
				}
				while( line.charAt(0) != '>'){
	    			t_seq = t_seq + line;
	    			line = fastaFile.readLine();
	    			// skip to first non_empty line
	    			if( line == null){
	    				break;
	    			}
	    			while( line.length() < 1){
	    				line = fastaFile.readLine();
	    			}
	    		}
				temp_seq.set_seq(t_seq);
				
				for(int i = 0; i < incTable.size(); i++){
	//				System.out.println(incTable.get(i));
	//				System.out.println(temp_seq.get_tag());
					if(temp_seq.get_tag().startsWith( (String) incTable.get(i) )) {
						//System.out.println(incTable.get(i));
						add_flag = true;
						// System.out.println(temp_seq.get_tag() + " " + incTable.get(i));
						break;
					}		
				}
				if(add_flag){
					fastaVector.add(new fasta_seq(temp_seq));
				}
				
				add_flag = false;
				t_seq = "";

				if (line==null)
				{
					break;
				}

			} // end while, here we have reached end of file
			
			fastaFile.close();
	}

	// ********************************************
	// Constructors
	// ********************************************
	
	public fasta(){
		//fastaVector = null;
		isProtein = true;
		isDNA = false;
		isRNA = false;
		//init_aa();
		//init_DNA();
		//init_RNA();
	}
	
	public fasta(fasta_seq f){
		fastaVector.add(new fasta_seq(f));
		isProtein = true;
		isDNA = false;
		isRNA = false;
		set_type("p");
		//init_aa();
		//init_DNA();
		//init_RNA();
	}
	
	public fasta(fasta f){
		for(int i = 0; i < f.num_seq(); i++){
			fasta_seq temp_seq = new fasta_seq(f.get_fasta(i));
			fastaVector.add(new fasta_seq(temp_seq));
		}
		isProtein = true;
		isDNA = false;
		isRNA = false;
		set_type("p");
		//init_aa();
		//init_DNA();
		//init_RNA();
	}
	
	public fasta(String s)
	    throws IOException, FileNotFoundException {
		read_fasta(s);
		isProtein = true;
		isDNA = false;
		isRNA = false;
		set_type("p");
		//init_aa();
		//init_DNA();
		//init_RNA();
	}
	
	public fasta(String s, String e)
		throws IOException, FileNotFoundException {
		read_fastaex(s, e);
		isProtein = true;
		isDNA = false;
		isRNA = false;
		set_type("p");
		//init_aa();
		//init_DNA();
		//init_RNA();
	}

	public fasta(String s, String e, int i)
		throws IOException, FileNotFoundException {
		read_fastainc(s, e);
		isProtein = true;
		isDNA = false;
		isRNA = false;
		set_type("p");
		//init_aa();
		//init_DNA();
		//init_RNA();
	}
	// ********************************************
	// Interface methods
	// ********************************************
	
	public fasta_seq get_fasta(int i){
		return (fasta_seq) fastaVector.get(i); 		
	}
	
	public Vector get_fasta(){
		return fastaVector;
	}
	
	public String get_seq(int i){
	    fasta_seq f = new fasta_seq();
	    f = (fasta_seq) fastaVector.get(i);
		return f.get_seq();
	}
	
	public String get_tag(int i){
	    fasta_seq f = new fasta_seq();
	    f = (fasta_seq) fastaVector.get(i);
		return f.get_tag();
	}
	
	public void add_fasta(int i, fasta_seq f){
		fasta_seq t = new fasta_seq("test", "atgc", "d");
		fastaVector.set(i, new fasta_seq(t));
	}
	
	public void add_fasta(fasta_seq f){
		fasta_seq t = new fasta_seq(f);
		fastaVector.add(new fasta_seq(t));
	}
	
	public void set_type(String type){
		String aa = "p";
		String dna = "d";
		String rna = "r";
		boolean OK = false;
		type.toLowerCase();
		
		if(aa.equals(type)){
			isDNA=false;
			isRNA=false;
			isProtein=true;
			OK = true;
			for(int i = 0; i < fastaVector.size(); i++)
			{
				fasta_seq t = new fasta_seq((fasta_seq) fastaVector.get(i));
				t.set_type("p");
				fastaVector.set(i,t);
				// System.out.println(t.get_type());
			}
		}
		
		if(dna.equals(type)){
			isDNA=true;
			isRNA=false;
			isProtein=false;
			OK = true;
			for(int i = 0; i < fastaVector.size(); i++)
			{
				fasta_seq t = new fasta_seq((fasta_seq) fastaVector.get(i));
				t.set_type("d");
				fastaVector.set(i,t);
				// System.out.println(t.get_type());
			}
			
		}
		if(rna.equals(type)){
			isDNA=false;
			isRNA=true;
			isProtein=false;
			OK = true;
			for(int i = 0; i < fastaVector.size(); i++)
			{
				fasta_seq t = new fasta_seq((fasta_seq) fastaVector.get(i));
				t.set_type("r");
				fastaVector.set(i,t);
			}
		}
		
		
		if(OK == false){
			System.out.println("Wrong type for sequnce type");
		}
	}
	
	public String get_seqtype(){
		if(isProtein){
			return "p";
		}
		if(isRNA){
			return "r";
		}
		if(isDNA){
			return "d";
		}
		return "";
	}
	// ********************************************
	// To string methods
	// ********************************************
	
	public String toString(int i){
			return (String) fastaVector.get(i);
	}

	// ********************************************
	// Public methods
	// ********************************************
	
	public int num_seq(){
		return fastaVector.size();
	}
	
	public int seq_length(int i){
		fasta_seq f = new fasta_seq((fasta_seq)fastaVector.get(0));
		return f.length();
	}
	
	public void clean(){
		
		fasta_seq temp_seq = new fasta_seq();
		String temp_string =  ""; 
		String clean_string = "";
		String s = "";
		
		if(isProtein){
			// for entire vector
			for(int i = 0; i < fastaVector.size(); i++){
				temp_seq = (fasta_seq) fastaVector.get(i);
				temp_string = temp_seq.get_seq();
				
				//for each sequence
				for(int j=0; j < temp_string.length(); j++){
					s = new Character(temp_string.charAt(j)).toString();
					//System.out.println(s);
					if(Bioutil.isAminoAcid(s)){
						clean_string = clean_string + s;

					}
				}
				temp_seq.set_seq(clean_string);
				fastaVector.set(i,temp_seq);
				temp_string = "";
				clean_string = "";
			}
		}
		if(isDNA){
			// for entire vector
			for(int i = 0; i < fastaVector.size(); i++){
				temp_seq = (fasta_seq) fastaVector.get(i);
				temp_string = temp_seq.get_seq();
				
				//for each sequence
				for(int j=0; j < temp_string.length(); j++){
					s = new Character(temp_string.charAt(j)).toString();
					if(Bioutil.isDNA(s)){
						clean_string = clean_string + s;
					}
				}
				temp_seq.set_seq(clean_string);
				fastaVector.set(i,temp_seq);
			}
		}
		
		if(isRNA){
			// for entire vector
			for(int i = 0; i < fastaVector.size(); i++){
				temp_seq = (fasta_seq) fastaVector.get(i);
				temp_string = temp_seq.get_seq();
				
				//for each sequence
				for(int j=0; j < temp_string.length(); j++){
					s = new Character(temp_string.charAt(j)).toString();
					if(Bioutil.isRNA(s)){
						clean_string = clean_string + s;
					}
				}
				temp_seq.set_seq(clean_string);
				fastaVector.set(i,temp_seq);
			}
		}
	}
	
	public void writeFasta(String fasta_filename)
		throws IOException, FileNotFoundException {
		PrintWriter fastaFile = new PrintWriter(new BufferedWriter(new FileWriter(fasta_filename)));
		
		for(int i =0; i < fastaVector.size(); i++){
			fastaFile.println(fastaVector.get(i).toString());
		}
		fastaFile.close();
	}
	
	public void splitLarge(String fastaIn_filename, String fastaOut_filename, int number)
		throws IOException, FileNotFoundException {
			
			
			// ********************
			// local variables
			// ********************
			
			String t_seq="";
			int num_file=0;
			int num_seq=0;


			
			// ***************************************************
			// read file section
			// ***************************************************
			
			// open fasta files
			BufferedReader fastaInFile = new BufferedReader ( new FileReader (fastaIn_filename));
	//		PrintWriter fastaOutFile = new PrintWriter(new BufferedWriter(new FileWriter(fastaOut_filename + "_" + num_file)));
			
			while (true){

				String line = fastaInFile.readLine();
				
				if(line == null){
					PrintWriter fastaOutFile = new PrintWriter(new BufferedWriter(new FileWriter(fastaOut_filename + "_" + num_file + ".faa")));
					fastaOutFile.write(t_seq);
					num_seq = 0;
					num_file++;
					t_seq = "";
					fastaOutFile.close();
					break;
				}

				//t_seq = t_seq + line;
				
				if(line.charAt(0) == '>'){
					t_seq+="\n"+line+"\n";
					num_seq++;
					//System.out.println("here");
				}else
					t_seq = t_seq + line;
				if(num_seq >= number){
					PrintWriter fastaOutFile = new PrintWriter(new BufferedWriter(new FileWriter(fastaOut_filename + "_" + num_file + ".faa")));
					fastaOutFile.write(t_seq);
					num_seq = 0;
					num_file++;
					t_seq = "";
					fastaOutFile.close();
				}
				
			}
			fastaInFile.close();
	}

}
